---
layout: m1x_soap
title: Create Your Own API
---

<ul>
    <li><a href='#CreateYourOwnAPI-CreatingaCustomAPIorExtendingtheCoreAPI'>Creating a Custom API or Extending the Core API</a>
        <ul>
            <li><a href='#CreateYourOwnAPI-1.CreatinganXMLFilethatWillDefinetheAPIResource'>1. Creating an XML File that Will Define the API Resource</a></li>
            <li><a href='#CreateYourOwnAPI-2.AddingaResourceNamedCustomer'>2. Adding a Resource Named Customer</a></li>
            <li><a href='#CreateYourOwnAPI-3.AddingFaults'>3. Adding Faults</a></li>
            <li><a href='#CreateYourOwnAPI-4.DescribingtheAccessControlList-ACL-fortheResource'>4. Describing the Access Control List (ACL) for the Resource</a></li>
            <li><a href='#CreateYourOwnAPI-5.CreatingPHPCode'>5. Creating PHP Code</a></li>
        </ul>
        <ul>
            <li><a href='#CreateYourOwnAPI-CreatingaCustomAdapter'>Creating a Custom Adapter</a>
            <ul>
                <li><a href='#CreateYourOwnAPI-CommonErrorMessages'>Common Error Messages</a></li>
            </ul>
        </ul>
        </li>
    </ul>
    </li>
</ul></div>


<h1><a name="CreateYourOwnAPI-CreatingaCustomAPIorExtendingtheCoreAPI"></a>Creating a Custom API or Extending the Core API</h1>

<p> The Core API allows you to manage a set of common resources used in Magento. However, you may choose to have your own set of resources to manage, or you may wish to extend the Core API to handle additional resources. </p>

<p> This tutorial leads you through the process of creating a custom API for a customer module that handles basic customer information. </p>

<p> <b>Note:</b> This tutorial applies to v1 of the API. </p>

<p> To learn more about the Core API, to read Magento Core API calls. </p>

<p> For general information about the Magento API, go to the Introduction.</p>

<h3><a name="CreateYourOwnAPI-1.CreatinganXMLFilethatWillDefinetheAPIResource"></a>1. Creating an XML File that Will Define the API Resource</h3>

<p> Create a file named <b>api.xml</b> in the /etc folder in the customer module. Start with the empty structure, as follows: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
        &lt;resources&gt;
        &lt;/resources&gt;
        &lt;acl&gt;
            &lt;resources&gt;
                &lt;all&gt;
                &lt;/all&gt;
            &lt;/resources&gt;
        &lt;/acl&gt;
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<h3><a name="CreateYourOwnAPI-2.AddingaResourceNamedCustomer"></a>2. Adding a Resource Named Customer</h3>

<p> Add an element named customer in the &lt;resources&gt; element. Add a &lt;methods&gt; element, with elements for list, create, info, update and remove methods for customer resource. </p>

<p> Note that: </p>
<ul>
	<li>list will return all customers</li>
	<li>create will create a new customer</li>
	<li>info will return data on a specified customer</li>
	<li>update will update data on a specified customer</li>
	<li>remove will delete data on a specified customer</li>
</ul>


<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
....
        &lt;resources&gt;
            &lt;customer translate="title" module="customer"&gt;
                &lt;title&gt;Customer Resource&lt;/title&gt;
                &lt;methods&gt;
                    &lt;list translate="title" module="customer"&gt;
                        &lt;title&gt;Retrive customers&lt;/title&gt;
                    &lt;/list&gt;
                    &lt;create translate="title" module="customer"&gt;
                        &lt;title&gt;Create customer&lt;/title&gt;
                    &lt;/create&gt;
                    &lt;info translate="title" module="customer"&gt;
                        &lt;title&gt;Retrieve customer data&lt;/title&gt;
                    &lt;/info&gt;
                    &lt;update translate="title" module="customer"&gt;
                        &lt;title&gt;Update customer data&lt;/title&gt;
                    &lt;/update&gt;
                    &lt;delete&gt;
                        &lt;title&gt;Delete customer&lt;/title&gt;
                    &lt;/delete&gt;
                &lt;/methods&gt;
                &lt;faults module="customer"&gt;
                &lt;/faults&gt;
            &lt;/customer&gt;
        &lt;/resources&gt;
....
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<h3><a name="CreateYourOwnAPI-3.AddingFaults"></a>3. Adding Faults</h3>

<p> The resource can return some faults, so add a &lt;faults&gt; element in the customer element, and list the various faults. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
....
        &lt;resources&gt;
            &lt;customer translate="title" module="customer"&gt;
....
                &lt;faults module="customer"&gt; &lt;!-- module="customer" specifies the module which will be used for translation. --&gt;
                    &lt;data_invalid&gt; &lt;!-- if we get invalid input data for customers --&gt;
                        &lt;code&gt;100&lt;/code &gt;
                        &lt;!-- we cannot know all the errors that can appear, their details can be found in error message for call --&gt;
                        &lt;message&gt;Invalid customer data. Details in error message.&lt;/message&gt;
                    &lt;/data_invalid&gt;
                    &lt;filters_invalid&gt;
                        &lt;code&gt;101&lt;/code &gt;
                        &lt;message&gt;Invalid filters specified. Details in error message.&lt;/message&gt;
                    &lt;/filters_invalid&gt;
                    &lt;not_exists&gt;
                        &lt;code&gt;102&lt;/code &gt;
                        &lt;message&gt;Customer doesn't exist.&lt;/message&gt;
                    &lt;/not_exists&gt;
                    &lt;not_deleted&gt;
                        &lt;code&gt;103&lt;/code &gt;
                        &lt;message&gt;Customer was not deleted. Details in error message.&lt;/message&gt;
                    &lt;/not_deleted&gt;
                &lt;/faults&gt;
            &lt;/customer&gt;
        &lt;/resources&gt;
....
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<h3><a name="CreateYourOwnAPI-4.DescribingtheAccessControlList-ACL-fortheResource"></a>4. Describing the Access Control List (ACL) for the Resource</h3>

<p> In order to prevent unauthorized access to our custom API, you must first list the resources that are restricted within the &lt;acl&gt; element. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
....
        &lt;acl&gt;
            &lt;resources&gt;
                    &lt;customer translate="title" module="customer"&gt;
                         &lt;title&gt;Customers&lt;/title&gt;
                         &lt;list translate="title" module="customer"&gt;
                            &lt;title&gt;View All&lt;/title&gt;
                         &lt;/list&gt;
                         &lt;create translate="title" module="customer"&gt;
                            &lt;title&gt;Create&lt;/title&gt;
                         &lt;/create&gt;
                         &lt;info translate="title" module="customer"&gt;
                            &lt;title&gt;Get Info&lt;/title&gt;
                         &lt;/info&gt;
                         &lt;update translate="title" module="customer"&gt;
                            &lt;title&gt;Update&lt;/title&gt;
                         &lt;/update&gt;
                         &lt;delete translate="title" module="customer"&gt;
                            &lt;title&gt;Delete&lt;/title&gt;
                         &lt;/delete&gt;
                    &lt;/customer&gt;
            &lt;/resources&gt;
        &lt;/acl&gt;
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<p> Then, map ACL resources to API resource methods by adding an &lt;acl&gt; element to each part of the resource that needs restricting: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
        &lt;resources&gt;
            &lt;customer translate="title" module="customer"&gt;
                &lt;title&gt;Customer Resource&lt;/title&gt;
                &lt;acl&gt;customer&lt;/acl&gt;
                &lt;methods&gt;
                    &lt;list translate="title" module="customer"&gt;
                        &lt;title&gt;Retrive customers&lt;/title&gt;
                        &lt;acl&gt;customer/list&lt;/acl&gt;
                    &lt;/list&gt;
                    &lt;create translate="title" module="customer"&gt;
                        &lt;title&gt;Create customer&lt;/title&gt;
                        &lt;acl&gt;customer/create&lt;/acl&gt;
                    &lt;/create&gt;
                    &lt;info translate="title" module="customer"&gt;
                        &lt;title&gt;Retrieve customer data&lt;/title&gt;
                        &lt;acl&gt;customer/info&lt;/acl&gt;
                    &lt;/info&gt;
                    &lt;update translate="title" module="customer"&gt;
                        &lt;title&gt;Update customer data&lt;/title&gt;
                        &lt;acl&gt;customer/update&lt;/acl&gt;
                    &lt;/update&gt;
                    &lt;delete&gt;
                        &lt;title&gt;Delete customer&lt;/title&gt;
                        &lt;acl&gt;customer/delete&lt;/acl&gt;
                    &lt;/delete&gt;
                &lt;/methods&gt;
              ....
            &lt;/customer&gt;
        &lt;/resources&gt;
....
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<h3><a name="CreateYourOwnAPI-5.CreatingPHPCode"></a>5. Creating PHP Code</h3>

<p> Next, write some PHP code to access the resources. Start by creating a class called Mage_Customer_Model_Customer_Api that extends Mage_Api_Model_Resource_Abstract. Save it into a file called <b>api.php</b>. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">class Mage_Customer_Model_Customer_Api extends Mage_Api_Model_Resource_Abstract
{

    public function create($customerData)
    {
    }

    public function info($customerId)
    {
    }

    public function items($filters)
    {
    }

    public function update($customerId, $customerData)
    {
    }

    public function delete($customerId)
    {
    }
}</pre>
		</div>
</div></div>

<p> Note that you cannot create method "list" because it’s a PHP keyword, so instead the method is named items. In order to make this work, add a &lt;method&gt; element into the &lt;list&gt; element in <b>api.xml</b>, as shown below.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
        &lt;resources&gt;
            &lt;customer translate="title" module="customer"&gt;
                &lt;model&gt;customer/api&lt;/model&gt; &lt;!-- our model --&gt;
                &lt;title&gt;Customer Resource&lt;/title&gt;
                &lt;acl&gt;customer&lt;/acl&gt;
                &lt;methods&gt;
                    &lt;list translate="title" module="customer"&gt;
                        &lt;title&gt;Retrive customers&lt;/title&gt;
                        &lt;method&gt;items&lt;/method&gt; &lt;!-- we have another method name inside our resource --&gt;
                        &lt;acl&gt;customer/list&lt;/acl&gt;
                    &lt;/list&gt;
....
                &lt;/methods&gt;
....
        &lt;/resources&gt;
....
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>

<p> Now add some simple functionality to the Mage_Customer_Model_Api methods you created. </p>

<p> 创建一个客户: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function create($customerData)
    {
        try {
            $customer = Mage::getModel('customer/customer')
                -&gt;setData($customerData)
                -&gt;save();
        } catch (Mage_Core_Exception $e) {
            $this-&gt;_fault('data_invalid', $e-&gt;getMessage());
            // We cannot know all the possible exceptions,
            // so let's try to catch the ones that extend Mage_Core_Exception
        } catch (Exception $e) {
            $this-&gt;_fault('data_invalid', $e-&gt;getMessage());
        }
        return $customer-&gt;getId();
    }</pre>
		</div>
</div></div>

<p> Retrieve customer info: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function info($customerId)
    {
        $customer = Mage::getModel('customer/customer')-&gt;load($customerId);
        if (!$customer-&gt;getId()) {
            $this-&gt;_fault('not_exists');
            // If customer not found.
        }
        return $customer-&gt;toArray();
        // We can use only simple PHP data types in webservices.
    }</pre>
		</div>
</div></div>

<p> Retrieve list of customers using filtering: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function items($filters)
    {
        $collection = Mage::getModel('customer/customer')-&gt;getCollection()
            -&gt;addAttributeToSelect('*');

        if (is_array($filters)) {
            try {
                foreach ($filters as $field =&gt; $value) {
                    $collection-&gt;addFieldToFilter($field, $value);
                }
            } catch (Mage_Core_Exception $e) {
                $this-&gt;_fault('filters_invalid', $e-&gt;getMessage());
                // If we are adding filter on non-existent attribute
            }
        }

        $result = array();
        foreach ($collection as $customer) {
            $result[] = $customer-&gt;toArray();
        }

        return $result;
    }</pre>
		</div>
</div></div>

<p> Update a customer: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function update($customerId, $customerData)
    {
        $customer = Mage::getModel('customer/customer')-&gt;load($customerId);

        if (!$customer-&gt;getId()) {
            $this-&gt;_fault('not_exists');
            // No customer found
        }

        $customer-&gt;addData($customerData)-&gt;save();
        return true;
    }</pre>
		</div>
</div></div>

<p> Delete a customer: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function delete($customerId)
    {
        $customer = Mage::getModel('customer/customer')-&gt;load($customerId);

        if (!$customer-&gt;getId()) {
            $this-&gt;_fault('not_exists');
            // No customer found
        }

        try {
            $customer-&gt;delete();
        } catch (Mage_Core_Exception $e) {
            $this-&gt;_fault('not_deleted', $e-&gt;getMessage());
            // Some errors while deleting.
        }

        return true;
    }</pre>
		</div>
</div></div>

<h2><a name="CreateYourOwnAPI-CreatingaCustomAdapter"></a>Creating a Custom Adapter</h2>

<p> In order to create custom webservice adapter, implement the Mage_Api_Model_Server_Adapter_Interface, which is shown below.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">interface Mage_Api_Model_Server_Adapter_Interface
{
    /**
     * Set handler class name for webservice
     *
     * @param string $handler
     * @return Mage_Api_Model_Server_Adapter_Interface
     */
    function setHandler($handler);

    /**
     * Retrive handler class name for webservice
     *
     * @return string [basc]
     */
    function getHandler();

    /**
     * Set webservice api controller
     *
     * @param Mage_Api_Controller_Action $controller
     * @return Mage_Api_Model_Server_Adapter_Interface
     */
    function setController(Mage_Api_Controller_Action $controller);

    /**
     * Retrive webservice api controller
     *
     * @return Mage_Api_Controller_Action
     */
    function getController();

    /**
     * Run webservice
     *
     * @return Mage_Api_Model_Server_Adapter_Interface
     */
    function run();

    /**
     * Dispatch webservice fault
     *
     * @param int $code
     * @param string $message
     */
    function fault($code, $message);

} // Class Mage_Api_Model_Server_Adapter_Interface End</pre>
		</div>
</div></div>

<p> Here is an example implementation for XML-RPC:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">class Mage_Api_Model_Server_Adapter_Customxmlrpc
    extends Varien_Object
    implements Mage_Api_Model_Server_Adapter_Interface
{
     /**
      * XmlRpc Server
      *
      * @var Zend_XmlRpc_Server
      */
     protected $_xmlRpc = null;

     /**
     * Set handler class name for webservice
     *
     * @param string $handler
     * @return Mage_Api_Model_Server_Adapter_Xmlrpc
     */
    public function setHandler($handler)
    {
        $this-&gt;setData('handler', $handler);
        return $this;
    }

    /**
     * Retrive handler class name for webservice
     *
     * @return string
     */
    public function getHandler()
    {
        return $this-&gt;getData('handler');
    }

     /**
     * Set webservice api controller
     *
     * @param Mage_Api_Controller_Action $controller
     * @return Mage_Api_Model_Server_Adapter_Xmlrpc
     */
    public function setController(Mage_Api_Controller_Action $controller)
    {
         $this-&gt;setData('controller', $controller);
         return $this;
    }

    /**
     * Retrive webservice api controller
     *
     * @return Mage_Api_Controller_Action
     */
    public function getController()
    {
        return $this-&gt;getData('controller');
    }

    /**
     * Run webservice
     *
     * @param Mage_Api_Controller_Action $controller
     * @return Mage_Api_Model_Server_Adapter_Xmlrpc
     */
    public function run()
    {
        $this-&gt;_xmlRpc = new Zend_XmlRpc_Server();
        $this-&gt;_xmlRpc-&gt;setClass($this-&gt;getHandler());
        $this-&gt;getController()-&gt;getResponse()
            -&gt;setHeader('Content-Type', 'text/xml')
            -&gt;setBody($this-&gt;_xmlRpc-&gt;handle());
        return $this;
    }

    /**
     * Dispatch webservice fault
     *
     * @param int $code
     * @param string $message
     */
    public function fault($code, $message)
    {
        throw new Zend_XmlRpc_Server_Exception($message, $code);
    }
} // Class Mage_Api_Model_Server_Adapter_Customxmlrpc End</pre>
		</div>
</div></div>

<p><b>Notes:</b> The setHandler, getHandler, setController and getController methods have a simple implementation that uses the Varien_Object getData and setData methods.</p>

<p> The run and fault methods are a native implementation for an XML-RPC webservice. The run method defines webservice logic in this adapter for creating an XML-RPC server to handle XML-RPC requests. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function run()
    {
        $this-&gt;_xmlRpc = new Zend_XmlRpc_Server();
        $this-&gt;_xmlRpc-&gt;setClass($this-&gt;getHandler());
        $this-&gt;getController()-&gt;getResponse()
            -&gt;setHeader('Content-Type', 'text/xml')
            -&gt;setBody($this-&gt;_xmlRpc-&gt;handle());
        return $this;
    }</pre>
		</div>
</div></div>

<p> The "fault" method allows you to send fault exceptions for XML-RPC service when handling requests. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">public function fault($code, $message)
    {
        throw new Zend_XmlRpc_Server_Exception($message, $code);
    }</pre>
		</div>
</div></div>

<h3><a name="CreateYourOwnAPI-CommonErrorMessages"></a>Common Error Messages</h3>

<p> The following are common error messages that you might receive when creating your own custom API. </p>

<p><b>Invalid API path</b></p>

<p> This error occurs when the methods listed in the <b>api.xml</b> file do not correspond exactly with those used in your PHP file. </p>

<p> 例如， in your api.xml file, you might have this: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: java; gutter: false">&lt;config&gt;
    &lt;api&gt;
        &lt;resources&gt;
            &lt;checkout_cart translate="title" module="checkout"&gt;
                &lt;model&gt;checkout/cart_api&lt;/model&gt;
                &lt;title&gt;Cart API&lt;/title&gt;
                &lt;methods&gt;
                    &lt;list translate="title" module="checkout"&gt;
                        &lt;title&gt;Retrieve cart data&lt;/title&gt;
                        &lt;method&gt;info&lt;/method&gt;
                    &lt;/list&gt;
                &lt;/methods&gt;
            &lt;/checkout_cart&gt;
        &lt;/resources&gt;
    ...
    &lt;/api&gt;
&lt;/config&gt;</pre>
		</div>
</div></div>


<p> You should have a corresponding info method in your PHP file. </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<div id="root">
		<pre class="theme: Default; brush: php; gutter: false">class Mage_Checkout_Model_Cart_Api extends Mage_Cart_Model_Api_Resource
{
    public function info()
    {
        ...
    }
}</pre>
		</div>
</div></div>

<p> If you are missing this method, the error "Invalid api path" will be returned. </p>
<?php include(__ROOT__ . 'footer.php'); ?>
